package com.youlai.boot.core.tenant.config;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.youlai.boot.core.tenant.model.entity.TenantDatasource;
import com.youlai.boot.core.tenant.service.TenantDatasourceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.List;

/**
 * 租户数据源初始化器
 * 在应用启动完成后，加载所有租户的数据源配置
 * 
 * 使用 ApplicationRunner 避免循环依赖问题
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicDataSourceConfig implements ApplicationRunner {

    private final DataSource dataSource;
    private final DefaultDataSourceCreator dataSourceCreator;
    private final TenantDatasourceService tenantDatasourceService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("======== 开始加载租户数据源 ========");
        
        try {
            // 查询所有启用的数据源配置
            List<TenantDatasource> datasourceConfigs = tenantDatasourceService.listEnabled();
            log.info("发现 {} 个启用的租户数据源配置", datasourceConfigs.size());

            DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;

            for (TenantDatasource config : datasourceConfigs) {
                try {
                    // 为每个租户创建并添加数据源
                    // 使用 tenantCode 作为数据源标识，因为 Mybatis-Plus 多租户插件通常使用 tenantId/tenantCode
                    // 这里为了与之前逻辑保持兼容或适应新逻辑，需要确认租户上下文中使用的是 ID 还是 Code
                    // 假设上下文中存储的是 TenantId (Long)，则转为 String
                    String dsKey = String.valueOf(config.getTenantId());
                    // 如果租户上下文使用的是 TenantCode，则应该是 config.getTenantCode()
                    
                    // 创建数据源配置
                    DataSourceProperty property = new DataSourceProperty();
                    property.setPoolName(config.getDatasourceName() + "-pool");
                    property.setDriverClassName(config.getDriverClassName());
                    property.setUrl(config.getUrl());
                    property.setUsername(config.getUsername());
                    property.setPassword(config.getPassword());
                    
                    // Hikari 连接池配置 (如果配置表中有值则使用表中的值，否则使用默认)
                    property.setLazy(true);
                    property.getHikari().setMinimumIdle(config.getMinIdle() != null ? config.getMinIdle() : 3);
                    property.getHikari().setMaximumPoolSize(config.getMaxActive() != null ? config.getMaxActive() : 20);
                    property.getHikari().setConnectionTimeout(config.getMaxWait() != null ? config.getMaxWait() : 30000L);
                    property.getHikari().setIdleTimeout(600000L);
                    property.getHikari().setMaxLifetime(1800000L);
                    
                    // 如果有验证查询
                    if (config.getValidationQuery() != null && !config.getValidationQuery().isEmpty()) {
                        property.getHikari().setConnectionTestQuery(config.getValidationQuery());
                    }

                    // 创建并添加数据源
                    DataSource tenantDataSource = dataSourceCreator.createDataSource(property);
                    ds.addDataSource(dsKey, tenantDataSource);

                    log.info("✓ 租户数据源加载成功: TenantId={}, Code={}, DB={}",
                            config.getTenantId(), config.getTenantCode(), config.getDatasourceName());

                } catch (Exception e) {
                    log.error("✗ 租户数据源加载失败: TenantId={}, Code={}, 原因: {}",
                            config.getTenantId(), config.getTenantCode(), e.getMessage(), e);
                }
            }

            log.info("======== 租户数据源加载完成，共加载 {} 个数据源 ========", datasourceConfigs.size());
            
        } catch (Exception e) {
            log.error("加载租户数据源时发生异常", e);
        }
    }
}
